<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head><meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"/>
<title>过滤字段</title><link href="../zdoc.css" rel="stylesheet" type="text/css"/><link href="../_rs/site.css" rel="stylesheet" type="text/css"/><script src="../_rs/site.js" language="Javascript"></script><script src="../_rs/jquery.js" language="Javascript"></script><script src="../_rs/z.js" language="Javascript"></script>
</head>
<body><a name="top"></a>
<div class="zdoc_header">过滤字段</div>
<div class="zdoc_author"><em>By:</em><b>zozoh</b><a href="mailto:zozohtnt@gmail.com">&lt;zozohtnt@gmail.com&gt;</a></div>
<div class="zdoc_body">
<ul class="zdoc_index_table">
<li>
<div><span class="num">1</span><a href="#为什么需要过滤字段">为什么需要过滤字段</a></div>
</li>
<li>
<div><span class="num">2</span><a href="#如何过滤字段的例子">如何过滤字段的例子</a></div>
</li>
<li>
<div><span class="num">3</span><a href="#字段过滤器的原理">字段过滤器的原理</a></div>
</li>
<li>
<div class="zdoc_folder"><span class="num">4</span><a href="#字段过滤器的创建">字段过滤器的创建</a></div>
<ul>
<li>
<div><span class="num">4.1</span><a href="#忽略少数字段">忽略少数字段</a></div>
</li>
<li>
<div><span class="num">4.2</span><a href="#忽略空值">忽略空值</a></div>
</li>
<li>
<div><span class="num">4.3</span><a href="#保留几个字段且忽略空值">保留几个字段且忽略空值</a></div>
</li>
<li>
<div><span class="num">4.4</span><a href="#忽略少数字段且忽略空值">忽略少数字段且忽略空值</a></div>
</li>
<li>
<div><span class="num">4.5</span><a href="#为多个实体设置字段过滤">为多个实体设置字段过滤</a></div>
</li>
</ul>
</li>
</ul>
<div class="hr"><b></b></div>
<h1><a name="为什么需要过滤字段"></a>为什么需要过滤字段</h1>
<div style="float:right;"><a href="#top">Top</a></div>
<p>某些时候，尤其是在更新对象的时候，用户希望忽略某些字段。通过注解 <a href="annotations.html">Nutz.Dao 实体注解</a> <span style="color:#AA7744;"><b>@Readonly</b></span> 可以达到 这个目的。但是更多的时候，对于 POJO 对象，只有在运行时，用户的程序才能决定哪些字段更新，哪些不更新。<span style="color:#AA7744;"><b>@Readonly</b></span> 注解可就达不到这个 目的了。</p>
<p>怎么办呢？ Nutz.Dao 提供了类似于 <a href="dynamic_table_name.html">动态表名</a> 的解决办法。</p>
<div class="hr"><b></b></div>
<h1><a name="如何过滤字段的例子"></a>如何过滤字段的例子</h1>
<div style="float:right;"><a href="#top">Top</a></div>
<p>如下代码，将只更新 Pet 的 id 和 name 字段：</p>
<pre>FieldFilter.create(Pet.class, "^id|name$").run(new Atom() {
	public void run() {
		Pet pet = dao.fetch(Pet.class, 24);
		pet.setName("ABC");
		pet.setNickname("XiaoBai");
		dao.update(pet);
	}
});
</pre>
<p></p>
<div class="hr"><b></b></div>
<h1><a name="字段过滤器的原理"></a>字段过滤器的原理</h1>
<div style="float:right;"><a href="#top">Top</a></div>
<p>字段过滤，不过是要在一个地方记录一下下面两个信息：</p>
<ol type="1">
<li>对什么实体</li>
<li>过滤哪些字段</li>
</ol>
<p>并且它希望 Nutz.Dao 自行能获取到这些信息。当然，ThreadLocal 就是一个很好的选择。实际上，你如果看看 FieldFilter 里面的方法，你其实就能猜到。为了能为多个实体保存字段过滤配置信息，它实际上在ThreadLoacal 里保存了自身的一个实例，同时，它自己有一个私有的  Map&lt;Class&lt;?&gt;, FieldMatcher&gt;，具体的，你可以看 FieldFilter 这个类的定义:</p>
<pre>public class FieldFilter {

    ...
    private static ThreadLocal&lt;FieldFilter&gt; FF = new ThreadLocal&lt;FieldFilter&gt;();
    ...
    private Map&lt;Class&lt;?&gt;, FieldMatcher&gt; map;
    ...

</pre>
<p>而且既然在 ThreadLocal 设置了数据，它就不得不考虑如何让你清除这个数据。因此，它的写法也保证了你一定会清掉你的数据了。</p>
<pre>FieldFilter ... run(new Atom(){   &lt;-- 开始将自身加入 ThreadLocal
    public void run(){
        // 这里是你的代码，你的 Dao 调用都会得到 ThreadLocal 中你对于实体字段过滤的设置
    }
});   &lt;-- run 方法结束前，会从 ThreadLocal 清除自身
</pre>
<p></p>
<div class="hr"><b></b></div>
<h1><a name="字段过滤器的创建"></a>字段过滤器的创建</h1>
<div style="float:right;"><a href="#top">Top</a></div>
<p>下面是一个最简单和常用的例子：</p>
<pre>FieldFilter.create(Pet.class, "^id|name$").run(new Atom(){
    public void run(){
        // TODO 你的 DAO 操作代码
    }
});
</pre>
<ul type="disc">
<li>这样，无论你查询或者更新等操作，对 Pet 这个实体只会针对能被正则表达式 "id|name" 匹配的字段进行操作
<ul type="circle">
<li>实际上，上例的正则表达式表示: <span style="color:#FF0000;"> 所有包括 id 和 name 字符的字段</span></li>
</ul>
</li>
<li>如果你想仅仅让 id 和 name 字段受到匹配，你的正则表达式最好写的严格一些，比如 "^id|name$"</li>
<li>当然，SQL 的条件部分不会受到字段过滤器的影响</li>
</ul>
<p>如果你读完上面的介绍，你应该就很了解字段过滤器如何使用了，但是你可能还有个几个小疑问:</p>
<ul type="disc">
<li>如果我字段比较多怎么办呢？</li>
<li>如果我想忽略所有之为空的字段怎么办呢？</li>
<li>如果我想同时为多个实体设置字段过滤怎么办呢？</li>
</ul>
<h2><a name="忽略少数字段"></a>忽略少数字段</h2>
<div style="float:right;"><a href="#top">Top</a></div>
<pre>FieldFilter.lock(Pet.class, "^last|age$").run(new Atom(){
    public void run(){
        // TODO 你的 DAO 操作代码
    }
});
</pre>
<p></p>
<h2><a name="忽略空值"></a>忽略空值</h2>
<div style="float:right;"><a href="#top">Top</a></div>
<pre>FieldFilter.create(Pet.class, true).run(new Atom(){
    public void run(){
        // TODO 你的 DAO 操作代码
    }
});
</pre>
<p></p>
<h2><a name="保留几个字段且忽略空值"></a>保留几个字段且忽略空值</h2>
<div style="float:right;"><a href="#top">Top</a></div>
<pre>FieldFilter.create(Pet.class,"^id|name|age|last$", true).run(new Atom(){
    public void run(){
        // TODO 你的 DAO 操作代码
    }
});
</pre>
<p></p>
<h2><a name="忽略少数字段且忽略空值"></a>忽略少数字段且忽略空值</h2>
<div style="float:right;"><a href="#top">Top</a></div>
<pre>FieldFilter.create(Pet.class, null, "^age|last$", true).run(new Atom(){
    public void run(){
        // TODO 你的 DAO 操作代码
    }
});
</pre>
<p></p>
<h2><a name="为多个实体设置字段过滤"></a>为多个实体设置字段过滤</h2>
<div style="float:right;"><a href="#top">Top</a></div>
<pre>FieldFilter.create(Pet.class, true)
           .set(Master.class, "^id|name$")
           .run(new Atom(){
    public void run(){
        // TODO 你的 DAO 操作代码
    }
});
</pre>
</div>
<div class="zdoc_footer"><em>By:</em><b>zozoh</b><a href="mailto:zozohtnt@gmail.com">&lt;zozohtnt@gmail.com&gt;</a></div>
</body>
</html>